/*
  ******************************************************************************
  * @file    usb_demo.c
  * @author  FreqChip Firmware Team
  * @version V1.0.0
  * @date    2021
  * @brief   USB module Demo.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2021 FreqChip.
  * All rights reserved.
  ******************************************************************************
*/
#include "usb_demo.h"

#include "driver_gpio.h"
#include "driver_spi.h"
#include "driver_system.h"
#include "driver_pmu.h"

#include "co_printf.h"
#include "co_log.h"
#include "sys_utils.h"
#include "ble_stack.h"

#include "usb_audio.h"
#include "driver_uart_ex.h"

volatile uint16_t MIC_Buffer[960];    // max 96K, 1channel, 16bit, 10packet
volatile uint32_t MIC_Packet;
volatile uint32_t MIC_RxCount;
volatile uint32_t MIC_TxCount;
volatile bool     MIC_Start;

volatile uint32_t Speaker_Buffer[192 * 2 * 10];    // max 96K, 2channel, 24bit, 10packet
volatile uint32_t Speaker_Packet;
volatile uint32_t Speaker_RxCount;
volatile uint32_t Speaker_TxCount;
volatile bool     Speaker_Start;

volatile bool Send_HID_Report;

/************************************************************************************
 * @fn      Porting_Speaker_fifo_status
 *
 * @brief   Whether the Speaker FIFO can store a packet of data
 */
bool Porting_Speaker_fifo_status(void)
{
    return 0;
}

void Porting_Speaker_write_fifo(uint32_t fu32_Size, uint32_t *fp_Data)
{

}

/************************************************************************************
 * @fn      Porting_Mic_fifo_status
 *
 * @brief   Whether the Mic FIFO store a packet of data.
 */
bool Porting_Mic_fifo_status(void)
{
    return 0;
}

void Porting_Mic_read_fifo(uint32_t fu32_Size, uint16_t *fp_Data)
{

}

/************************************************************************************
 * @fn      usb_demo
 *
 * @brief   usb demo
 */
void usb_demo(void)
{
    pmu_usb_pad_ctrl(true);

    NVIC_ClearPendingIRQ(USBMCU_IRQn);
    NVIC_SetPriority(USBMCU_IRQn, 0);
    NVIC_EnableIRQ(USBMCU_IRQn);

    usb_device_init();
    usb_audio_init();
    
    usb_DP_Pullup_Enable();

    while(1)
    {
        if (Porting_Mic_fifo_status())
        {
            uint32_t Mic_Packet_Length = usb_Audio_get_Mic_Packet_Length();

            MIC_RxCount = MIC_Packet * Mic_Packet_Length;

            Porting_Mic_read_fifo(Mic_Packet_Length, (uint16_t *)&MIC_Buffer[MIC_RxCount]);

            MIC_Packet += 1;

            if (MIC_Packet >= 10) 
            {
                MIC_Packet = 0;
            }

            if (MIC_Packet >= 5 && MIC_Start == false) 
            {
                usb_selecet_endpoint(ENDPOINT_1);
                
                // start the frist packet transmission
                if (usb_Endpoints_GET_TxPkrRdy() == false) 
                {
                    usb_write_fifo(ENDPOINT_1, (uint8_t *)&MIC_Buffer[MIC_TxCount], Mic_Packet_Length*2);
                    usb_Endpoints_SET_TxPktRdy();

                    MIC_TxCount += Mic_Packet_Length;

                    MIC_Start = true;
                }
                // start fail
                else 
                {
                    MIC_Packet  = 0;
                    MIC_RxCount = 0;
                    MIC_TxCount = 0;
                    MIC_Start   = false;
                }
            }

            if (MIC_Start) 
            {
                if (MIC_RxCount == MIC_TxCount) 
                {
                    MIC_Packet  = 0;
                    MIC_RxCount = 0;
                    MIC_TxCount = 0;
                    MIC_Start   = false;
                }
            }
        }

        if (Send_HID_Report)
        {
            if (usb_hid_send_Audio_report() == 0)
                Send_HID_Report = 0;
        }

        if (Speaker_Start) 
        {
            switch (usb_Audio_get_Speaker_Bit_Width())
            {
                case USB_AUDIO_DATA_WIDTH_16BIT:
                {
                    if (Porting_Speaker_fifo_status())
                    {
                        uint32_t Speaker_Packet_Length = usb_Audio_get_Speaker_Packet_Length();

                        Porting_Speaker_write_fifo(Speaker_Packet_Length, (uint32_t *)&Speaker_Buffer[Speaker_TxCount]);

                        Speaker_TxCount += Speaker_Packet_Length;

                        if (Speaker_TxCount >= Speaker_Packet_Length*10) 
                        {
                            Speaker_TxCount = 0;
                        }

                        if (Speaker_TxCount == Speaker_RxCount) 
                        {
                            Speaker_Packet  = 0;
                            Speaker_RxCount = 0;
                            Speaker_TxCount = 0;
                            Speaker_Start   = false;
                        }
                    }
                }break;

                case USB_AUDIO_DATA_WIDTH_24BIT:
                {
                    if (Porting_Speaker_fifo_status())
                    {
                        uint32_t Speaker_Packet_Length = usb_Audio_get_Speaker_Packet_Length();

                        Porting_Speaker_write_fifo(Speaker_Packet_Length*2, (uint32_t *)&Speaker_Buffer[Speaker_TxCount]);

                        Speaker_TxCount += (Speaker_Packet_Length*2);

                        if (Speaker_TxCount >= Speaker_Packet_Length*2*10) 
                        {
                            Speaker_TxCount = 0;
                        }

                        if (Speaker_TxCount == Speaker_RxCount) 
                        {
                            Speaker_Packet  = 0;
                            Speaker_RxCount = 0;
                            Speaker_TxCount = 0;
                            Speaker_Start   = false;
                        }
                    }
                }break;

                default:break;
            }
        }
    }
}

